package com.dd.cloud.user.service.doctor.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dd.cloud.common.constants.IntegralConstants;
import com.dd.cloud.common.exception.ZekeException;
import com.dd.cloud.common.interceptor.UserInterceptor;
import com.dd.cloud.common.utils.ObjectUtils;
import com.dd.cloud.common.vo.LoginInfo;
import com.dd.cloud.user.entity.doctor.*;
import com.dd.cloud.user.mapper.doctor.DoctorIntegralMapper;
import com.dd.cloud.user.mapper.doctor.DoctorTaskListMapper;
import com.dd.cloud.user.mapper.doctor.DoctorTaskTimeRecordMapper;
import com.dd.cloud.user.mq.MQConfig;
import com.dd.cloud.user.mq.RabbitSend;
import com.dd.cloud.user.service.doctor.*;
import jodd.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.print.Doc;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 医生任务列表 服务实现类
 * </p>
 *
 * @author czg
 * @since 2024-01-30
 */
@Service
@Slf4j
public class DoctorTaskListServiceImpl extends ServiceImpl<DoctorTaskListMapper, DoctorTaskList> implements IDoctorTaskListService {

    @Autowired
    private IDoctorIntegralService doctorIntegralService;

    @Autowired
    private IDoctorUserService doctorUserService;

    @Autowired
    private IDoctorDetailService doctorDetailService;

    @Autowired
    private IDoctorTaskRecordService doctorTaskRecordService;

    @Autowired
    private RedisTemplate redisTemplate;

    public String userFamilyKey = "integral:inviteUserFamily:";

    public String readStudyKey = "integral:readStudyKey:";

    public String taskKey = "integral:taskKey:";

    @Autowired
    private DoctorIntegralMapper doctorIntegralMapper;

    @Override
    public List<DoctorTaskList> queryDoctorOneTaskList() {
        LoginInfo loginInfo = UserInterceptor.getLoginUserInfo().get();
        LambdaQueryWrapper<DoctorTaskList> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(DoctorTaskList::getStatus, 1)
                .orderByAsc(DoctorTaskList::getId);
        List<DoctorTaskList> taskLists = this.list(queryWrapper);
        LambdaQueryWrapper<DoctorTaskRecord> taskRecordLambdaQueryWrapper = new LambdaQueryWrapper<>();
        taskRecordLambdaQueryWrapper.in(DoctorTaskRecord::getType, 2, 3, 17)
                .eq(DoctorTaskRecord::getStatus, 1)
                .eq(DoctorTaskRecord::getDoctorId, loginInfo.getId());
        List<DoctorTaskRecord> recordList = doctorTaskRecordService.list(taskRecordLambdaQueryWrapper);
        Map<Integer, DoctorTaskRecord> recordMap = null;
        recordMap = recordList.stream().collect(Collectors.toMap(DoctorTaskRecord::getType, Function.identity()));
        List<DoctorTaskList> doctorTaskLists = new ArrayList<>();
        Map<Integer, DoctorTaskList> map = taskLists.stream().collect(Collectors.toMap(DoctorTaskList::getType, Function.identity()));
        DoctorUser doctorUser = doctorUserService.getById(loginInfo.getId());
        Integer isCertification = doctorUser.getIsCertification();
        //资质认证
        DoctorTaskList twoTask = map.get(IntegralConstants.IntegralType.TWO_TYPE);
        String res = "";
        DoctorTaskRecord record = null;
        if (isCertification == 1) {
            twoTask.setIsOver(1);
        } else {
            twoTask.setIsOver(0);
            if (recordMap != null) {
                record = recordMap.get(IntegralConstants.IntegralType.TWO_TYPE);
                if (record != null && record.getIsShow() == 1) {
                    twoTask.setIsOver(1);
                }
            }
            res = "1";
        }
        if (record != null) {
            twoTask.setCreateDate(record.getCreateDate());
        }
        Integer twoIsShow = getIsShow(IntegralConstants.IntegralType.TWO_TYPE, recordMap, res);
        twoTask.setIsShow(twoIsShow);
        doctorTaskLists.add(twoTask);
        //完善个人简历
        LambdaQueryWrapper<DoctorDetail> doctorDetailLambdaQueryWrapper = new LambdaQueryWrapper<>();
        doctorDetailLambdaQueryWrapper.eq(DoctorDetail::getDoctorId, loginInfo.getId());
        DoctorDetail doctorDetail = doctorDetailService.getOne(doctorDetailLambdaQueryWrapper);
        DoctorTaskList threeTypeTask = map.get(IntegralConstants.IntegralType.THREE_TYPE);
        DoctorTaskRecord threeRecord = recordMap.get(IntegralConstants.IntegralType.THREE_TYPE);
        if (threeRecord != null) {
            threeTypeTask.setCreateDate(threeRecord.getCreateDate());
        }
        Integer threeIsShow = getIsShow(IntegralConstants.IntegralType.THREE_TYPE, recordMap, doctorDetail.getIntroduction());
        threeTypeTask.setIsShow(threeIsShow);
        doctorTaskLists.add(threeTypeTask);
        //完善个人头像
        DoctorTaskList seventeenTypeTask = map.get(IntegralConstants.IntegralType.SEVENTEEN_TYPE);
        Integer seventeenIsShow = getIsShow(IntegralConstants.IntegralType.SEVENTEEN_TYPE, recordMap, doctorDetail.getAvatar());
        seventeenTypeTask.setIsShow(seventeenIsShow);
        DoctorTaskRecord fourRecord = recordMap.get(IntegralConstants.IntegralType.THREE_TYPE);
        if (fourRecord != null) {
            seventeenTypeTask.setCreateDate(fourRecord.getCreateDate());
        }
        doctorTaskLists.add(seventeenTypeTask);
        //邀请医生
        DoctorTaskList fourTypeTask = map.get(IntegralConstants.IntegralType.FIVE_TYPE);
        LambdaQueryWrapper<DoctorIntegral> doctorIntegralLambdaQueryWrapper = new LambdaQueryWrapper<>();
        doctorIntegralLambdaQueryWrapper.eq(DoctorIntegral::getType, IntegralConstants.IntegralType.FIVE_TYPE)
                .ne(DoctorIntegral::getStatus, -2);
        Integer count = doctorIntegralService.count(doctorIntegralLambdaQueryWrapper);
        fourTypeTask.setCount(count).setIsShow(1).setIsOver(0);
        doctorTaskLists.add(fourTypeTask);
        return taskLists;
    }

    @Override
    public List<DoctorTaskList> queryDoctorTwoTaskList() {
        LoginInfo loginInfo = UserInterceptor.getLoginUserInfo().get();
        Integer doctorId = loginInfo.getId();
        LambdaQueryWrapper<DoctorTaskList> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(DoctorTaskList::getStatus, 1)
                .orderByAsc(DoctorTaskList::getId);
        List<DoctorTaskList> doctorTaskLists = this.list(queryWrapper);
        List<DoctorIntegral> doctorIntegrals = doctorIntegralMapper.queryDoctorTwoTaskList();
        LambdaQueryWrapper<DoctorTaskTimeRecord> taskTimeRecordLambdaQueryWrapper = new LambdaQueryWrapper<>();
        taskTimeRecordLambdaQueryWrapper.eq(DoctorTaskTimeRecord::getStatus, 1)
                .eq(DoctorTaskTimeRecord::getDoctorId, loginInfo.getId())
                .eq(DoctorTaskTimeRecord::getCreateDate, LocalDate.now());
        List<DoctorTaskTimeRecord> doctorTaskTimeRecords = doctorTaskTimeRecordService.list(taskTimeRecordLambdaQueryWrapper);
        Map<Integer, DoctorTaskTimeRecord> doctorTaskTimeRecordMap = doctorTaskTimeRecords.stream().collect(Collectors.toMap(DoctorTaskTimeRecord::getType, Function.identity()));
        Map<Integer, DoctorIntegral> doctorIntegralMap = null;
        if (doctorIntegrals != null) {
            doctorIntegralMap = doctorIntegrals.stream().collect(Collectors.toMap(DoctorIntegral::getType, Function.identity()));
        }
        Map<Integer, DoctorTaskList> map = doctorTaskLists.stream().collect(Collectors.toMap(DoctorTaskList::getType, Function.identity()));
        List<DoctorTaskList> doctorTaskListList = new ArrayList<>();
        for (DoctorTaskList doctorTaskList : doctorTaskLists) {
            if (doctorTaskList.getType().equals(IntegralConstants.IntegralType.SEVEN_TYPE)
                    || doctorTaskList.getType().equals(IntegralConstants.IntegralType.NINE_TYPE)) {
                //邀请患者填写
                Integer num = (Integer) redisTemplate.opsForValue().get(userFamilyKey + IntegralConstants.IntegralType.SEVEN_TYPE + ":" + doctorId);
                DoctorTaskList sevenTask = map.get(IntegralConstants.IntegralType.SEVEN_TYPE);
                if (doctorTaskList.getType().equals(IntegralConstants.IntegralType.SEVEN_TYPE)) {
                    setTaskValue(num, 200, 5, doctorTaskList, doctorIntegralMap);
                } else if (doctorTaskList.getType().equals(IntegralConstants.IntegralType.NINE_TYPE)) {
                    setTaskValue(num, 500, 20, doctorTaskList, doctorIntegralMap);
                }
                doctorTaskListList.add(sevenTask);
            } else if (doctorTaskList.getType().equals(IntegralConstants.IntegralType.TWELVE_TYPE)
                    || doctorTaskList.getType().equals(IntegralConstants.IntegralType.THIRTEEN_TYPE)
                    || doctorTaskList.getType().equals(IntegralConstants.IntegralType.FOURTEEN_TYPE)) {
                DoctorTaskList task = map.get(IntegralConstants.IntegralType.TWELVE_TYPE);
                Integer num = (Integer) redisTemplate.opsForValue().get(taskKey + IntegralConstants.IntegralType.TWELVE_TYPE + ":" + doctorId);
                setTaskValue(num, 70, 10, task, doctorIntegralMap);
                doctorTaskListList.add(task);
            } else if (doctorTaskList.getType().equals(IntegralConstants.IntegralType.TWENTY_ONE)
                    || doctorTaskList.getType().equals(IntegralConstants.IntegralType.TWENTY_TWO)) {
                //查看圈子
                Integer num = (Integer) redisTemplate.opsForValue().get(taskKey + IntegralConstants.IntegralType.TWENTY_ONE + ":" + doctorId);
                setTaskValue(num, 20, 2, doctorTaskList, doctorIntegralMap);
                doctorTaskListList.add(doctorTaskList);
            } else if (doctorTaskList.getType().equals(IntegralConstants.IntegralType.ELEVEN_TYPE) ||
                    doctorTaskList.getType().equals(IntegralConstants.IntegralType.FIFTEEN_TYPE)) {
                Integer num = null;
                if (doctorTaskList.getType().equals(IntegralConstants.IntegralType.ELEVEN_TYPE)) {
                    num = (Integer) redisTemplate.opsForValue().get(readStudyKey + IntegralConstants.IntegralType.ELEVEN_TYPE + ":" + doctorId);
                } else if (doctorTaskList.getType().equals(IntegralConstants.IntegralType.FIFTEEN_TYPE)) {
                    num = (Integer) redisTemplate.opsForValue().get(taskKey + IntegralConstants.IntegralType.ELEVEN_TYPE + ":" + doctorId);
                }
                setTaskValue(num, 100, 5, doctorTaskList, doctorIntegralMap);
                doctorTaskListList.add(doctorTaskList);
            }
        }
        return doctorTaskListList;
    }


    @Autowired
    private IDoctorTaskTimeRecordService doctorTaskTimeRecordService;

    @Autowired
    private RabbitSend rabbitSend;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addTaskIntegral(Integer type, Integer time) {
        if (time < 1) {
            return;
        }
        LoginInfo loginInfo = UserInterceptor.getLoginUserInfo().get();
        LambdaQueryWrapper<DoctorTaskTimeRecord> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(DoctorTaskTimeRecord::getDoctorId, loginInfo.getId())
                .eq(DoctorTaskTimeRecord::getType, type)
                .eq(DoctorTaskTimeRecord::getCreateDate, LocalDate.now())
                .eq(DoctorTaskTimeRecord::getStatus, 1)
                .last("limit 1");
        DoctorTaskTimeRecord doctorTaskTimeRecord = doctorTaskTimeRecordService.getOne(queryWrapper);
        Integer count = 0;
        if (doctorTaskTimeRecord == null) {
            count = time / 15;
            log.info("今日首次赠送次数:{}", count);
            DoctorTaskTimeRecord newTaskTimeRecord = new DoctorTaskTimeRecord();
            newTaskTimeRecord.setDoctorId(loginInfo.getId())
                    .setTime(time)
                    .setType(type)
                    .setNum(count)
                    .setStatus(1)
                    .setCreateDate(LocalDate.now());
            Boolean flag = doctorTaskTimeRecordService.save(newTaskTimeRecord);
            if (!flag) {
                throw new ZekeException("保存失败");
            }

        } else {
            //赠送积分
            Integer num = doctorTaskTimeRecord.getNum();
            Integer oldTime = doctorTaskTimeRecord.getTime();
            log.info("今日时间:{},今日阅读时间:{},已赠送次数:{}", LocalDate.now(), oldTime, num);
            Integer curTime = (oldTime - 15 * num) + time;
            log.info("还剩阅读时间:{}", curTime);
            count = curTime / 15;
            log.info("可赠送次数:{}", count);
            doctorTaskTimeRecord.setTime(doctorTaskTimeRecord.getTime() + time)
                    .setNum(doctorTaskTimeRecord.getNum() + count);
            Boolean flag = doctorTaskTimeRecordService.updateById(doctorTaskTimeRecord);
            if (!flag) {
                throw new ZekeException("更新失败");
            }
        }
        if (count > 0) {
            for (int i = 0; i < count; i++) {
                String params = type + "-" + loginInfo.getId();
                log.info("学习奖励积分,参数为{}", params);
                rabbitSend.sendMessage(MQConfig.INTEGRAL_EXCHANGE, MQConfig.INTEGRAL_QUEUE, params);
            }
        }
    }

    private void setTaskValue(Integer giveNum,
                              Integer total,
                              Integer div, DoctorTaskList task,
                              Map<Integer, DoctorIntegral> doctorIntegralMap) {
        if (giveNum == null) {
            task.setCount(0);
        } else {
            Integer count = giveNum / div;
            task.setCount(count);
            if (giveNum.equals(total)) {
                task.setIsOver(1);
                LocalDateTime dateTime = getTime(IntegralConstants.IntegralType.NINE_TYPE, doctorIntegralMap);
                task.setCreateDate(dateTime);
            }
        }
    }

    private LocalDateTime getTime(Integer type, Map<Integer, DoctorIntegral> doctorIntegralMap) {
        if (doctorIntegralMap != null) {
            DoctorIntegral doctorIntegral = doctorIntegralMap.get(type);
            if (doctorIntegral != null) {
                return doctorIntegral.getCreateDate();
            }
        }
        return null;
    }

    private Integer getIsShow(Integer type, Map<Integer, DoctorTaskRecord> recordMap, String res) {
        if (recordMap == null) {
            if (StringUtil.isBlank(res)) {
                return 1;
            } else {
                return 0;
            }
        } else {
            DoctorTaskRecord doctorTaskRecord = recordMap.get(type);
            //老数据兼容 已认证 此表不会有记录 不显示 未认证 老数据 需要显示
            if (doctorTaskRecord == null) {
                if (StringUtil.isBlank(res)) {
                    return 1;
                } else {
                    return 0;
                }
            } else {
                return doctorTaskRecord.getIsShow();
            }
        }
    }
}
